package cn.bonoon.kernel.web.components;

import static cn.bonoon.kernel.util.StringHelper.isEmpty;

import java.lang.reflect.Method;
import java.util.Calendar;

import cn.bonoon.kernel.IOptionArray;
import cn.bonoon.kernel.descriptors.UIPropertyAccessor;
import cn.bonoon.kernel.util.StringHelper;
import cn.bonoon.kernel.web.annotations.components.AsMonthly;
import cn.bonoon.kernel.web.annotations.components.AsSelector;
import cn.bonoon.kernel.web.annotations.components.EnumSelector;
import cn.bonoon.kernel.web.annotations.components.SelectorOption;
import cn.bonoon.kernel.web.html.UIPropertyBuilder;
import cn.bonoon.kernel.web.html.form.ComponentPropertyParser;

public class SelectorComponent extends AbstractComponent {

	private final AsSelector com;

	public SelectorComponent(ComponentPropertyParser property, UIPropertyAccessor accessor, AsSelector asSelector) {
		super(property, accessor);
		this.com = asSelector;
	}

	private void __optionString(StringBuilder html, String bindedName, String value, String text){
		html.append("<option value='").append(value);
		html.append("' #if(${").append(bindedName).append('.').append(componentName);
		html.append("}==\"").append(value).append("\")selected='selected'#end>").append(text).append("</option>");
	}
	private void __optionNumber(StringBuilder html, String bindedName, String value, String text){
		__optionNumber(html, bindedName, componentName, value, text);
	}
	private void __optionNumber(StringBuilder html, String bindedName, String componentName, String value, String text){
		html.append("<option value='").append(value);
		html.append("' #if(${").append(bindedName).append('.').append(componentName);
		html.append("}==").append(value).append(")selected='selected'#end>").append(text).append("</option>");
	}
	
	@Override
	protected void parser(UIPropertyBuilder builder) {
		StringBuilder html = builder.getInitHtml();
		String bindedName = builder.getBindedName();
		html.append("<select");
		__component(html);
		
		AsMonthly monthly = accessor.getAnnotation(AsMonthly.class);
		if(null != monthly){
			html.append('>');
			Calendar cal = Calendar.getInstance();
			int year = cal.get(Calendar.YEAR);
			int start = year + monthly.start(), end = year + monthly.end();
			for(; start <= end; start ++){
				String ss = String.valueOf(start);
				__optionNumber(html, bindedName, ss, ss);
			}
			html.append("</select> 年 ");
			if(!monthly.annual()){
				String month = monthly.value();
				html.append("<select name='").append(month).append("'>");
				for(int i = 0; i < 12; i++){
					String v = String.valueOf(i), n = String.valueOf(i + 1);
					__optionNumber(html, bindedName, month, v, n);
				}
				html.append("</select> 月");
			}
		}else{
			html.append(" style='width:").append(componentWidth()).append("px;'");
			if(com.comboBox()){
			
				html.append('>');
	
				__parseOption(html, bindedName);
				
				html.append("</select>");
	
				StringBuilder block = builder.getInitBlock();
				block.append("jQuery('#").append(componentId).append("').bupbasecombo({editable:false");
				if(com.multiple()){
					block.append(",multiple:true");
				}
				String oc = com.onChange();
				if(StringHelper.isNotEmpty(oc)){
					block.append(",onChange:function(newValue, oldValue){var id=jQuery('#");
					block.append(builder.getEntityId()).append("').val();if(!jQuery.isNumeric(id)){id=0;}");
					block.append(oc).append("}");
				}
				block.append("});");
			}else{
				if(com.multiple()){//多选的情况下不加"--请选择--"这样的选项，否则也会把这个选项选中，那就不好了
					html.append(" multiple='multiple'>");
				}else{
					html.append('>').append(com.title());
					
				} 
				
				__parseOption(html, bindedName);
				
				html.append("</select>");
				
				String oc = com.onChange();
				StringBuilder block = builder.getInitBlock();
				if(StringHelper.isNotEmpty(oc)){
	//				block.append("jQuery('#").append(componentId).append("').bupbasecombo({onChange:function(newValue, oldValue){var id=jQuery('#");
	//				block.append(builder.getEntityId()).append("').val();if(!jQuery.isNumeric(id)){id=0;}");
	//				block.append(oc).append("}});");
					
					block.append("jQuery('#").append(componentId).append("').change(function(){var id=jQuery('#");
					block.append(builder.getEntityId()).append("').val();if(!jQuery.isNumeric(id)){id=0;}");
					block.append(oc).append("});");
				}
			}
		}
	}

	private void __parseOption(StringBuilder html, String bindedName) {
		com.type().parse(html, com.modelOptions());
		boolean isNum = accessor.isNumber();
		for (int i = 0; i < com.value().length; i++) {
			SelectorOption opt = com.value()[i];
			String v = opt.value(), n = opt.name();
			if (isEmpty(v)){
				v = Integer.toString(i);
			} else if (isEmpty(n)){
				n = v;
			}
			if(isNum){
				__optionNumber(html, bindedName, v, n);
			}else{
				__optionString(html, bindedName, v, n);
			}
		}
		IOptionArray optionArray = accessor.getOptionArray();
		if(null != optionArray){
			String[] options = optionArray.array();
			int offset = optionArray.offset();
			int[] excludes = optionArray.excludes();
			
			if(null != excludes){
				NEXT : for (int i = optionArray.start(), len = optionArray.end(); i < len; i++) {
					for(int j : excludes){
						if(j == i){ continue NEXT; }
					}
					__option(html, bindedName, isNum, options, offset, i);
				}
			}else{
				for(int i = optionArray.start(), len = optionArray.end(); i < len; i++){
					__option(html, bindedName, isNum, options, offset, i);
				}
			}
		}
		EnumSelector es = accessor.getAnnotation(EnumSelector.class);
		if(null != es){
			try{
				Class<?> cls = es.value();
				Method m = cls.getMethod("values");
				Method t = cls.getMethod(es.textProperty());
				Object[] vs = (Object[])m.invoke(null);
				int i = 0;
				for(Object v : vs){
					__optionNumber(html, bindedName, String.valueOf(i++), (String)t.invoke(v));
				}
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private void __option(StringBuilder html, String bindedName, boolean isNum, String[] options, int offset, int i) {
		String n = options[i];
		if(isNum){
			String v = Integer.toString(i + offset);
			__optionNumber(html, bindedName, v, n);
		}else{
			__optionString(html, bindedName, n, n);
		}
	}
}
